home *** CD-ROM | disk | FTP | other *** search
- /*
- * lmem.c -- memory initialization and allocation; also parses arguments.
- */
-
- #include "link.h"
- #include "tproto.h"
- #include "globals.h"
-
- /*
- * The following code is operating-system dependent [@lmem.01]. It includes
- * files that are system dependent.
- */
-
- #if PORT
- /* nothing is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA || ARM || ATARI_ST || MACINTOSH || VMS
- /* nothing is needed */
- #endif /* AMIGA || ARM || ATARI_ST || ... */
-
- #if OS2
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif /* OS@ */
-
- #if MSDOS
- #if MWC
- #include <stat.h>
- #endif /* MWC */
- #if LATTICE
- #include <types.h>
- #include <stat.h>
- #endif /* LATTICE */
- #if MICROSOFT || INTEL_386 || ZTC_386 || HIGHC_386 || WATCOM
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif /* MICROSOFT || INTEL_386 || ... */
- #if TURBO
- #include <sys/stat.h>
- #endif /* TURBO */
- #endif /* MSDOS */
-
- #if MVS || VM
- #if SASC
- #include <fcntl.h>
- #endif /* SASC */
- #endif /* MVS || VM */
-
- #if UNIX
- #ifndef ATT3B
- #ifdef CRAY
- #define word word_fubar
- #include <sys/types.h>
- #include <sys/stat.h>
- #undef word
- #else /* CRAY */
- #ifndef XWindows
- #include <sys/types.h>
- #endif /* XWindows */
- #include <sys/stat.h>
- #endif /* CRAY */
- #endif /* ATT3B */
- #endif /* UNIX */
-
- /*
- * End of operating-system specific code.
- */
-
- /*
- * Prototypes.
- */
-
- hidden struct lfile *alclfile Params((char *name));
- hidden int canread Params((char *file));
- hidden int trypath Params((char *name,char *file));
-
- #ifdef DeBugLinker
- hidden novalue dumpfiles Params((noargs));
- #endif /* DeBugLinker */
-
- #ifdef MultipleRuns
- hidden novalue freelfile Params((struct lfile *p));
- #endif /* MultipleRuns */
-
- /*
- * Memory initialization
- */
-
- struct gentry **lghash; /* hash area for global table */
- struct ientry **lihash; /* hash area for identifier table */
- struct fentry **lfhash; /* hash area for field table */
-
- struct lentry *lltable; /* local table */
- struct centry *lctable; /* constant table */
- struct ipc_fname *fnmtbl; /* table associating ipc with file name */
- struct ipc_line *lntable; /* table associating ipc with line number */
-
- char *lsspace; /* string space */
- word *labels; /* label table */
- char *codeb; /* generated code space */
-
- struct ipc_fname *fnmfree; /* free pointer for ipc/file name table */
- struct ipc_line *lnfree; /* free pointer for ipc/line number table */
- word lsfree; /* free index for string space */
- char *codep; /* free pointer for code space */
-
- struct fentry *lffirst; /* first field table entry */
- struct fentry *lflast; /* last field table entry */
- struct gentry *lgfirst; /* first global table entry */
- struct gentry *lglast; /* last global table entry */
-
- static char *ipath; /* path for iconx */
-
- #ifdef MultipleRuns
- extern word pc;
- extern int fatals;
- extern int nlflag;
- extern int lstatics;
- extern int nfields;
- #endif /* MultipleRuns */
-
- /*
- * linit - scan the command line arguments and initialize data structures.
- */
- novalue linit()
- {
- struct gentry **gp;
- struct ientry **ip;
- struct fentry **fp;
-
- llfiles = NULL; /* Zero queue of files to link. */
-
- #ifdef EnvVars
- ipath = getenv(IPATH);
- #else /* EnvVars */
- ipath = NULL;
- #endif /* EnvVars */
-
- if (ipath == NULL)
-
- /*
- * The following code is operating-system dependent [@lmem.02]. Set default
- * for IPATH.
- */
-
- #if PORT
- /* something is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA
- /*
- * There is no environment, so set IPATH to the null string. The
- * current directory is searched anyway and there is no symbol
- * to force current path search.
- */
- ipath = "";
- #endif /* AMIGA */
-
- #if ARM
- ipath = "Icon: Lib:Icon.";
- #endif /* ARM */
-
- #if ATARI_ST || UNIX
- ipath = ".";
- #endif /* ATARI_ST || UNIX */
-
- #if MSDOS || OS2
- ipath = ";";
- #endif /* MSDOS || OS2 */
-
- #if MACINTOSH
- #if MPW || LSC
- ipath = ":";
- #endif /* MPW || LSC */
- #endif /* MACINTOSH */
-
- #if MVS
- #if SASC
- ipath = "iconlib ddn:::lib";
- #else /* SASC */
- ipath = "";
- #endif /* SASC */
- #endif /* MVS */
-
- #if VM
- ipath = "";
- #endif /* VM */
-
- #if VMS
- ipath = "[]";
- #endif /* VMS */
-
- /*
- * End of operating-system specific code.
- */
-
- /*
- * Allocate the various data structures that are used by the linker.
- */
- lghash = (struct gentry **) tcalloc(ghsize, sizeof(struct gentry *));
- lihash = (struct ientry **) tcalloc(ihsize, sizeof(struct ientry *));
- lfhash = (struct fentry **) tcalloc(fhsize, sizeof(struct fentry *));
-
- lltable = (struct lentry *) tcalloc(lsize, sizeof(struct lentry));
- lctable = (struct centry *) tcalloc(csize, sizeof(struct centry));
-
- lnfree = lntable = (struct ipc_line*)tcalloc(nsize,sizeof(struct ipc_line));
-
- lsspace = (char *) tcalloc(stsize, sizeof(char));
- lsfree = 0;
-
- fnmtbl = (struct ipc_fname *) tcalloc(fnmsize, sizeof(struct ipc_fname));
- fnmfree = fnmtbl;
-
- labels = (word *) tcalloc(maxlabels, sizeof(word));
- codep = codeb = (char *) tcalloc(maxcode, 1);
-
- lffirst = NULL;
- lflast = NULL;
- lgfirst = NULL;
- lglast = NULL;
-
- /*
- * Zero out the hash tables.
- */
- for (gp = lghash; gp < &lghash[ghsize]; gp++)
- *gp = NULL;
- for (ip = lihash; ip < &lihash[ihsize]; ip++)
- *ip = NULL;
- for (fp = lfhash; fp < &lfhash[fhsize]; fp++)
- *fp = NULL;
-
- #ifdef MultipleRuns
-
- /*
- * Initializations required for repeated program runs.
- */
-
- pc = 0; /* In lcode.c */
- nrecords = 0; /* In lglob.c */
-
- #ifdef EventMon
- colmno = 0; /* In link.c */
- #endif /* EventMon */
-
- lineno = 0; /* In link.c */
- fatals = 0; /* In link.c */
- nlflag = 0; /* In llex.c */
- lstatics = 0; /* In lsym.c */
- nfields = 0; /* In lsym.c */
- #endif /* MultipleRuns */
-
- /*
- * Install "main" as a global variable in order to insure that it
- * is the first global variable. iconx/start.s depends on main
- * being global number 0.
- */
- putglobal(instid("main"), F_Global, 0, 0);
- }
-
- #ifdef DeBugLinker
- /*
- * dumplfiles - print the list of files to link. Used for debugging only.
- */
-
- novalue dumplfiles()
- {
- struct lfile *p,*lfls;
-
- fprintf(stderr,"lfiles:\n");
- lfls = llfiles;
- while (p = getlfile(&lfls))
- fprintf(stderr,"'%s'\n",p->lf_name);
- fflush(stderr);
- }
- #endif /* DeBugLinker */
-
- /*
- * alsolink - create an lfile structure for the named file and add it to the
- * end of the list of files (llfiles) to generate link instructions for.
- */
- static char *pptr;
- novalue alsolink(name)
- char *name;
- {
- struct lfile *nlf, *p;
- char file[256], ok;
-
- ok = 0;
- if (canread(name)) {
- ok++;
- strcpy(file, name);
- }
- else {
- /*
- * Can't find name in current directory so try paths in
- * IPATH if there are any. (IPATH cannot override the
- * current-directory-first strategy so there is probably
- * no reason to initialize IPATH to the various current
- * directory markers as is done above, since this will
- * only result in a duplicate failed search. Note that
- * the access test which is done above in some systems
- * will have already caused ilink to exit if name is
- * not found in the current directory anyway so ipath
- * was never able to search other paths first in any case.)
- */
-
- #ifdef Xver
- xver(lmem.1)
- #endif /* Xver */
-
- #ifndef Xver
- pptr = ipath;
- #endif /* Xver */
-
- while (trypath(name, file)) {
- if (canread(file)) {
- ok++;
- break;
- }
- }
- }
-
- if (!ok)
- quitf("cannot resolve reference to file '%s'",name);
-
- nlf = alclfile(file);
- if (llfiles == NULL) {
- llfiles = nlf;
- }
- else {
- p = llfiles;
- while (p->lf_link != NULL) {
- if (strcmp(p->lf_name,file) == 0)
- return;
- p = p->lf_link;
- }
- if (strcmp(p->lf_name,file) == 0)
- return;
- p->lf_link = nlf;
- }
- }
-
- /*
- * getlfile - return a pointer (p) to the lfile structure pointed at by lptr
- * and move lptr to the lfile structure that p points at. That is, getlfile
- * returns a pointer to the current (wrt. lptr) lfile and advances lptr.
- */
- struct lfile *getlfile(lptr)
- struct lfile **lptr;
- {
- struct lfile *p;
-
- if (*lptr == NULL)
- return (struct lfile *)NULL;
- else {
- p = *lptr;
- *lptr = p->lf_link;
- return p;
- }
- }
-
- /*
- * canread - see if file can be read and be sure that it's just an
- * ordinary file.
- */
- static int canread(file)
- char *file;
- {
-
- /*
- * The following code is operating-system dependent [@lmem.03]. Check to see if
- * .u1 file can be read.
- */
-
- #if PORT
- /* something is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA || ATARI_ST || VMS
- if (access(file,4) == 0)
- return 1;
- #endif /* AMIGA || ATARI_ST || VMS */
-
- #if ARM
- {
- FILE *f;
- if ((f = fopen(file,ReadText)) != NULL) {
- fclose(f);
- return 1;
- }
- }
- #endif /* ARM */
-
- #if MACINTOSH
- #if MPW || LSC
- {
- FILE *f;
- if ((f = fopen(file,ReadText)) != NULL) {
- fclose(f);
- return 1;
- }
- }
- #endif /* MPW || LSC */
- #endif /* MACINTOSH */
-
- #if MSDOS || OS2 || UNIX
- #if INTEL_386
- char lclname[MaxFileName];
- if (access( makename(lclname,(char *)NULL,file,U1Suffix), 4 ) == 0 )
- return 1;
- #else /* INTEL_386 */
- struct stat statb;
- if (access(file,4) == 0) {
- stat(file,&statb);
- if (statb.st_mode & S_IFREG)
- return 1;
- }
- #endif /* INTEL_386 */
- #endif /* MSDOS || ... */
-
- #if MVS || VM
- char lclname[MaxFileName];
- #if SASC
- if (access(makename(lclname,(char*)NULL,file,U1Suffix),R_OK) == 0)
- return 1;
- #else /* SASC */
- FILE *f; /* can't use access because it will */
- /* accept LRECL, etc. */
-
- if ((f = fopen(makename(lclname,(char *)NULL,file,U1suffix),
- ReadText)) != NULL) {
- fclose(f);
- return 1;
- }
- #endif /* SASC */
- #endif /* MVS || VM */
-
- /*
- * End of operating-system specific code.
- */
-
- return 0;
- }
-
- #ifdef Xver
- xver(lmem.2)
- #endif /* Xver */
-
- #ifndef Xver
- /*
- * trypath - form a file name in file by concatenating name onto the
- * next path element.
- */
- static int trypath(name,file)
- char *name, *file;
- {
- char c;
-
- #if MACINTOSH && MPW
- #define PATH_SEP ','
- #else /* MACINTOSH && MPW */
- #define PATH_SEP ' '
- #endif /* MACINTOSH && MPW */
-
- while (*pptr == PATH_SEP)
- pptr++;
- if (!*pptr)
- return 0;
- do {
- c = (*file++ = *pptr++);
- }
- while (c != PATH_SEP && c);
- pptr--;
- file--;
-
- /*
- * The following code is operating-system dependent [@lmem.04]. Append path
- * character.
- */
-
- #if PORT
- /* nothing is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA
- file--;
- switch (*file) {
-
- case ':':
- case '/':
- file++;
- break; /* add nothing, delimiter already there */
- default:
- *file++ = '/';
- }
- #endif /* AMIGA */
-
- #if ARM || ATARI_ST || MACINTOSH || VM || VMS
- /* nothing is needed */
- #endif /* ARM || ATARI_ST || MACINTOSH ... */
-
- #if MVS
- *file++ = '(';
- #endif /* MVS */
-
- #if UNIX || MSDOS || OS2
- #if HIGHC_386
- *file++ = '\\';
- #else /* HIGHC_386 */
- *file++ = '/'; /* should check for delimiter */
- #endif /* HIGHC_386 */
- #endif /* UNIX || MSDOS || OS2 */
-
- /*
- * End of operating-system specific code.
- */
-
- while (*file++ = *name++);
-
- #if MVS
- file[-1] = ')';
- #endif /* MVS */
- *file = 0;
- return 1;
- }
- #endif /* Xver */
-
- /*
- * alclfile - allocate an lfile structure for the named file, fill
- * in the name and return a pointer to it.
- */
- static struct lfile *alclfile(name)
- char *name;
- {
- struct lfile *p;
-
- p = (struct lfile *) alloc(sizeof(struct lfile));
- p->lf_link = NULL;
- p->lf_name = salloc(name);
- return p;
- }
-
- #ifdef MultipleRuns
- /*
- * freelfile - free memory of an lfile structure.
- */
- static novalue freelfile(p)
- struct lfile *p;
- {
- free((char *)p->lf_name);
- free((char *) p);
- }
- #endif /* MultipleRuns */
-
- /*
- * lmfree - free memory used by the linker
- */
- novalue lmfree()
- {
- struct fentry *fp, *fp1;
- struct gentry *gp, *gp1;
- struct rentry *rp, *rp1;
- struct ientry *ip, *ip1;
- struct lfile *lf, *nlf;
- int i;
-
- for (i = 0; i < ihsize; ++i)
- for (ip = lihash[i]; ip != NULL; ip = ip1) {
- ip1 = ip->i_blink;
- free((char *)ip);
- }
-
- free((char *) lghash); lghash = NULL;
- free((char *) lihash); lihash = NULL;
- free((char *) lfhash); lfhash = NULL;
- free((char *) lltable); lltable = NULL;
- free((char *) lctable); lctable = NULL;
- free((char *) lntable); lntable = NULL;
- free((char *) lsspace); lsspace = NULL;
- free((char *) fnmtbl); fnmtbl = NULL;
- free((char *) labels); labels = NULL;
- free((char *) codep); codep = NULL;
-
- for (fp = lffirst; fp != NULL; fp = fp1) {
- for(rp = fp->f_rlist; rp != NULL; rp = rp1) {
- rp1 = rp->r_link;
- free((char *)rp);
- }
- fp1 = fp->f_nextentry;
- free((char *)fp);
- }
- lffirst = NULL;
- lflast = NULL;
-
- for (gp = lgfirst; gp != NULL; gp = gp1) {
- gp1 = gp->g_next;
- free((char *)gp);
- }
- lgfirst = NULL;
- lglast = NULL;
-
- #ifdef MultipleRuns
- for (lf = llfiles; lf != NULL; lf = nlf) {
- nlf = lf->lf_link;
- freelfile(lf);
- }
- llfiles = NULL;
-
- #if MACINTOSH
- #if MPW
- /* #pragma unused(nlf,lf) */
- #endif /* MPW */
- #endif /* MACINTOSH */
- #endif /* MultipleRuns */
-
- }
-